package amd64

import (
	"fmt"
	"sync"
)

const lock_no_unlock = 5000000

type RegRun struct {
	lock   *sync.Mutex
	RDI    bool
	RSP    bool
	R8     bool
	RDX    bool
	R9     bool
	RBP    bool
	RSI    bool
	R10    bool
	RCX    bool
	RBX    bool
	Thread bool
	R11    bool
	R12    bool
	R13    bool
	R14    bool
	R15    bool
	RAX    bool
}

func NewRegRun(Thread bool) *RegRun {
	ret := &RegRun{
		Thread: Thread,
		RAX:    false,
		RBX:    false,
		RCX:    false,
		RDX:    false,
		RSP:    false,
		RBP:    false,
		RSI:    false,
		RDI:    false,
		R8:     false,
		R9:     false,
		R10:    false,
		R11:    false,
		R12:    false,
		R13:    false,
		R14:    false,
		R15:    false,
	}
	ret.lock = new(sync.Mutex)
	return ret
}

func (reg *RegRun) RetReg(bits int8) RegEnum {
	for i := 0; i < lock_no_unlock; i++ {
		reg, ok := reg.tryRetReg(bits)
		if ok {
			return reg
		}
	}
	panic(fmt.Errorf("大概率死锁了 ptr=%p %+v", reg, reg))
}

func (reg *RegRun) tryRetReg(bits int8) (ret RegEnum, ok bool) {
	if reg.Thread {
		reg.lock.Lock()
		defer reg.lock.Unlock()
	}
	if !reg.RAX {
		reg.RAX = true
		return RAX, true
	}
	if !reg.RBX {
		reg.RBX = true
		return RBX, true
	}
	if !reg.RCX {
		reg.RCX = true
		return RCX, true
	}
	if !reg.RDX {
		reg.RDX = true
		return RDX, true
	}
	if !reg.R8 {
		reg.R8 = true
		return R8, true
	}
	if !reg.R9 {
		reg.R9 = true
		return R9, true
	}
	if !reg.R10 {
		reg.R10 = true
		return R10, true
	}
	if !reg.R11 {
		reg.R11 = true
		return R11, true
	}
	if !reg.R12 {
		reg.R12 = true
		return R12, true
	}
	if !reg.R13 {
		reg.R13 = true
		return R13, true
	}
	if !reg.R14 {
		reg.R14 = true
		return R14, true
	}
	if !reg.R15 {
		reg.R15 = true
		return R15, true
	}
	return 0, false
}

func (reg *RegRun) CloseReg(regenum RegEnum) {
	if reg.Thread {
		reg.lock.Lock()
		defer reg.lock.Unlock()
	}
	switch regenum {
	case RAX:
		reg.RAX = false
	case RBX:
		reg.RBX = false
	case RCX:
		reg.RCX = false
	case RDX:
		reg.RDX = false
	case R8:
		reg.R8 = false
	case R9:
		reg.R9 = false
	case R10:
		reg.R10 = false
	case R11:
		reg.R11 = false
	case R12:
		reg.R12 = false
	case R13:
		reg.R13 = false
	case R14:
		reg.R14 = false
	case R15:
		reg.R15 = false
	}
}

type SseRegRun struct {
	Thread bool
	Xmm0   bool
	Xmm1   bool
	Xmm2   bool
	Xmm3   bool
	Xmm4   bool
	Xmm5   bool
	Xmm6   bool
	Xmm7   bool
	lock   sync.Mutex
}

func NewSseRegRun(Thread bool) *SseRegRun {
	return &SseRegRun{
		Thread: Thread,
		Xmm0:   false,
		Xmm1:   false,
		Xmm2:   false,
		Xmm3:   false,
		Xmm4:   false,
		Xmm5:   false,
		Xmm6:   false,
		Xmm7:   false,
	}
}

func (reg *SseRegRun) RetReg() RegEnum {
	for i := 0; i < lock_no_unlock; i++ {
		reg, ok := reg.tryRetReg()
		if ok {
			return reg
		}
	}
	panic(fmt.Errorf("大概率死锁了 ptr=%p\n %+v", reg, reg))
}

func (reg *SseRegRun) tryRetReg() (ret RegEnum, ok bool) {
	if reg.Thread {
		reg.lock.Lock()
		defer reg.lock.Unlock()
	}
	if !reg.Xmm0 {
		reg.Xmm0 = true
		return Xmm0, true
	}
	if !reg.Xmm1 {
		reg.Xmm1 = true
		return Xmm1, true
	}
	if !reg.Xmm2 {
		reg.Xmm2 = true
		return Xmm2, true
	}
	if !reg.Xmm3 {
		reg.Xmm3 = true
		return Xmm3, true
	}
	if !reg.Xmm4 {
		reg.Xmm4 = true
		return Xmm4, true
	}
	if !reg.Xmm5 {
		reg.Xmm5 = true
		return Xmm5, true
	}
	if !reg.Xmm6 {
		reg.Xmm6 = true
		return Xmm6, true
	}
	if !reg.Xmm7 {
		reg.Xmm7 = true
		return Xmm7, true
	}
	return 0, false
}

func (reg *SseRegRun) CloseReg(regenum RegEnum) {
	if reg.Thread {
		reg.lock.Lock()
		defer reg.lock.Unlock()
	}
	switch regenum {
	case Xmm0:
		reg.Xmm0 = false
	case Xmm1:
		reg.Xmm1 = false
	case Xmm2:
		reg.Xmm2 = false
	case Xmm3:
		reg.Xmm3 = false
	case Xmm4:
		reg.Xmm4 = false
	case Xmm5:
		reg.Xmm5 = false
	case Xmm6:
		reg.Xmm6 = false
	case Xmm7:
		reg.Xmm7 = false
	}
}
